#include"chessmap.h"
#include"mi.h"
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<vector>

using namespace std;

checker c[13][32];
vector<wuma> w1,w2;
vector<youma> yo1,yo2;
vector<archer> a1,a2;
vector<baseground> b1,b2;
vector<checker> waiting;

int nw1=-1,nw2=-1,ny1=-1,ny2=-1,na1=-1,na2=-1;

int caldst(int x1, int y1, int x2, int y2) {
	return abs(x1 - x2) + abs(y1 - y2);
}

void map_print() {
	system("cls");
	for (int i = 1; i <= 11; i++) {
		for (int j = 1; j <= 30; j++) {
			switch (c[i][j].kind)
			{
			case 2:
				cout << "* ";
				break;
			case 6:
				cout << "+ ";
				break;
			default:
				cout << c[i][j].kind<<' ';
			} 
		}
		cout << '\n';
	}
}

void wait_insert(checker chk) {
	vector<checker>::iterator it = waiting.begin();
	int t = chk.time;
	while (!waiting.empty() && it!=waiting.end() && (*it).time < t)it++;
	switch (chk.kind)
	{
	case 4:
		while (!waiting.empty() && it != waiting.end() && (*it).kind == 3)it++;
		break;
	case 5:
		while (!waiting.empty() && it != waiting.end() && ((*it).kind == 3 || (*it).kind == 4))it++;
		break;
	default:
		break;
	}
	while (!waiting.empty() && it != waiting.end() && (*it).kind == chk.kind && (*it).No < chk.No)it++;
	waiting.insert(it, chk);
}

void map_init() {
	int tempx, tempy,n;
	for (int j = 1; j <= 30; j++)
		c[0][j] = c[12][j] = 1;
	for (int i = 1; i <= 11; i++)
		c[i][0] = c[i][31] = 1;
	b1.push_back(baseground(0));
	b2.push_back(baseground(1));
	c[5][1] = c[6][1] = c[7][1] = c[5][2] = c[6][2] = c[7][2] = checker(2, -1, 0, 0);
	c[5][29] = c[6][29] = c[7][29] = c[5][30] = c[6][30] = c[7][30] = checker(2, -1, 1, 1);
	c[3][1] = c[3][2] = c[4][1] = c[4][2] = c[4][3] = c[5][3] = c[5][4] = c[6][3] = c[6][4] = c[7][3] = c[7][4] = c[8][1] = c[8][2] = c[8][3] = c[9][1] = c[9][2] = checker(6);
	n = 1;
	while (n--) {
		map_print();
		cout << "Player 1:\n";
		cout << "Please select a \'+\' to put your bubing by input its position(row col sep by blank space) (e.g.:3 1)\n";
		cin >> tempx >> tempy;
		c[tempx][tempy] = checker(3, 3, ++nw1, 0);
		wait_insert(c[tempx][tempy]);
		w1.push_back(wuma(tempx, tempy, 0));
	}
	n = 1;
	while (n--) {
		map_print();
		cout << "Player 1:\n";
		cout << "Please select a \'+\' to put your gongbing by input its position(row col sep by blank space) (e.g.:3 1)\n";
		cin >> tempx >> tempy;
		c[tempx][tempy] = checker(5, 4, ++na1, 0);
		wait_insert(c[tempx][tempy]);
		a1.push_back(archer(tempx, tempy, 0));
	}
	map_print();
	cout << "Player 1:\n";
	cout << "Please select a \'+\' to put your qibing by input its position(row col sep by blank space) (e.g.:3 1)\n";
	cin >> tempx >> tempy;
	c[tempx][tempy] = checker(4, 4, ++ny1, 0);
	wait_insert(c[tempx][tempy]);
	yo1.push_back(youma(tempx, tempy, 0));
	for (int i = 3; i < 10; i++)
		for (int j = 1; j < 5; j++)
			if (c[i][j].kind == 6)
				c[i][j].kind = 0;
	c[3][30] = c[3][29] = c[4][30] = c[4][29] = c[4][28] = c[5][28] = c[5][27] = c[6][28] = c[6][27] = c[7][28] = c[7][27] = c[8][30] = c[8][29] = c[8][28] = c[9][30] = c[9][29] = checker(6);
	n = 1;
	while (n--) {
		map_print();
		cout << "Player 2:\n";
		cout << "Please select a \'+\' to put your bubing by input its position(row col sep by blank space) (e.g.:3 1)\n";
		cin >> tempx >> tempy;
		c[tempx][tempy] = checker(3, 3, ++nw2, 1);
		wait_insert(c[tempx][tempy]);
		w2.push_back(wuma(tempx, tempy, 1));
	}
	n = 1;
	while (n--) {
		map_print();
		cout << "Player 2:\n";
		cout << "Please select a \'+\' to put your gongbing by input its position(row col sep by blank space) (e.g.:3 1)\n";
		cin >> tempx >> tempy;
		c[tempx][tempy] = checker(5, 4, ++na2, 1);
		wait_insert(c[tempx][tempy]);
		a2.push_back(archer(tempx, tempy, 1));
	}
	map_print();
	cout << "Player 2:\n";
	cout << "Please select a \'+\' to put your qibing by input its position(row col sep by blank space) (e.g.:3 1)\n";
	cin >> tempx >> tempy;
	c[tempx][tempy] = checker(4, 4, ++ny2, 1);
	wait_insert(c[tempx][tempy]);
	yo2.push_back(youma(tempx, tempy, 1));
	for (int i = 3; i < 10; i++)
		for (int j = 27; j < 31; j++)
			if (c[i][j].kind == 6)
				c[i][j].kind = 0;
	map_print();
}

void movechess(int fromx,int fromy,int tox,int toy,int mv) {
	vector<Node> openlist;
	vector<Node>::iterator p;
	int min,tempx,tempy,i,j;
	Node nd[13][32],*temp=nullptr;
	nd[fromx][fromy]= Node(fromx, fromy, 0, caldst(fromx,fromy,tox,toy), nullptr,1);
	nd[fromx][fromy].father = &nd[fromx][fromy];
	openlist.push_back(nd[fromx][fromy]);
	while (!openlist.empty()) {
		min = openlist[0].value;
		j = 0;
		for (p = openlist.begin(),i=0; p+i != openlist.end(); i++)
			if ((*(p + i)).value < min) {
				j = i;
			}
		temp = &nd[openlist[j].x][openlist[j].y];
		openlist.erase(openlist.begin() + j);
		if (temp->x == tox && temp->y == toy)
			break;
		temp->lst = 2;
		tempx = temp->x + 1;
		tempy = temp->y;
		if (c[tempx][tempy].kind == 0 && nd[tempx][tempy].lst != 2) {
			if (nd[tempx][tempy].lst == 0) {
				nd[tempx][tempy] = Node(tempx, tempy, temp->G + 1, caldst(tempx,tempy,tox,toy), temp, 1);
				openlist.push_back(nd[tempx][tempy]);
			}
			else {
				if (nd[tempx][tempy].G > temp->G + 1) {
					nd[tempx][tempy].G = temp->G + 1;
					nd[tempx][tempy].father = temp;
					nd[tempx][tempy].value = nd[tempx][tempy].G + nd[tempx][tempy].H;
				}
			}
		}
		tempx = temp->x - 1;
		tempy = temp->y;
		if (c[tempx][tempy].kind == 0 && nd[tempx][tempy].lst != 2) {
			if (nd[tempx][tempy].lst == 0) {
				nd[tempx][tempy] = Node(tempx, tempy, temp->G + 1, caldst(tempx, tempy, tox, toy), temp, 1);
				openlist.push_back(nd[tempx][tempy]);
			}
			else {
				if (nd[tempx][tempy].G > temp->G + 1) {
					nd[tempx][tempy].G = temp->G + 1;
					nd[tempx][tempy].father = temp;
					nd[tempx][tempy].value = nd[tempx][tempy].G + nd[tempx][tempy].H;
				}
			}
		}
		tempx = temp->x;
		tempy = temp->y + 1;
		if (c[tempx][tempy].kind == 0 && nd[tempx][tempy].lst != 2) {
			if (nd[tempx][tempy].lst == 0) {
				nd[tempx][tempy] = Node(tempx, tempy, temp->G + 1, caldst(tempx, tempy, tox, toy), temp, 1);
				openlist.push_back(nd[tempx][tempy]);
			}
			else {
				if (nd[tempx][tempy].G > temp->G + 1) {
					nd[tempx][tempy].G = temp->G + 1;
					nd[tempx][tempy].father = temp;
					nd[tempx][tempy].value = nd[tempx][tempy].G + nd[tempx][tempy].H;
				}
			}
		}
		tempx = temp->x;
		tempy = temp->y - 1;
		if (c[tempx][tempy].kind == 0 && nd[tempx][tempy].lst != 2) {
			if (nd[tempx][tempy].lst == 0) {
				nd[tempx][tempy] = Node(tempx, tempy, temp->G + 1, caldst(tempx, tempy, tox, toy), temp, 1);
				openlist.push_back(nd[tempx][tempy]);
			}
			else {
				if (nd[tempx][tempy].G > temp->G + 1) {
					nd[tempx][tempy].G = temp->G + 1;
					nd[tempx][tempy].father = temp;
					nd[tempx][tempy].value = nd[tempx][tempy].G + nd[tempx][tempy].H;
				}
			}
		}
	}
	while (temp!=nullptr && caldst(temp->x, temp->y, fromx, fromy) > mv)
		temp = temp->father;
	if (temp != nullptr) {
		c[temp->x][temp->y] = c[fromx][fromy];
		c[fromx][fromy] = checker(0);
	}
	int kind,player;
	checker ck = c[temp->x][temp->y];
	kind = ck.kind;
	player = ck.player;
	switch (kind)
	{
	case 3:
		if (player == 0) {
			w1[ck.No].x = temp->x;
			w1[ck.No].y = temp->y;
		}
		else {
			w2[ck.No].x = temp->x;
			w2[ck.No].y = temp->y;
		}
		break;
	case 4:
		if (ck.player == 0) {
			yo1[ck.No].x = temp->x;
			yo1[ck.No].y = temp->y;
		}
		else {
			yo2[ck.No].x = temp->x;
			yo2[ck.No].y = temp->y;
		}
		break;
	case 5:
		if (ck.player == 0) {
			a1[ck.No].x = temp->x;
			a1[ck.No].y = temp->y;
		}
		else {
			a2[ck.No].x = temp->x;
			a2[ck.No].y = temp->y;
		}
	}
}

void timegoon() {
	vector<checker>::iterator p;
	for (p = waiting.begin(); p != waiting.end(); p++) {
		(*p).time--;
	}
}

void attack(checker ck) {
	
}

void turn(checker &ck) {
	map_print();
	int x, y, atk,mv, kind, temp, tox, toy;
	string sd;
	kind = ck.kind;
	switch (kind)
	{
	case 3:
		sd = "bubing";
		if (ck.player == 0) {
			x = w1[ck.No].x;
			y = w1[ck.No].y;
			atk = w1[ck.No].atk;
			mv = w1[ck.No].mv;
		}
		else {
			x = w2[ck.No].x;
			y = w2[ck.No].y;
			atk = w2[ck.No].atk;
			mv = w2[ck.No].mv;
		}
		break;
	case 4:
		sd = "qibing";
		if (ck.player == 0) {
			x = yo1[ck.No].x;
			y = yo1[ck.No].y;
			atk = yo1[ck.No].atk;
			mv = yo1[ck.No].mv;
		}
		else {
			x = yo2[ck.No].x;
			y = yo2[ck.No].y;
			atk = yo2[ck.No].atk;
			mv = yo2[ck.No].mv;
		}
		break;
	case 5:
		sd = "gongbing";
		if (ck.player == 0) {
			x = a1[ck.No].x;
			y = a1[ck.No].y;
			atk = a1[ck.No].atk;
			mv = a1[ck.No].mv;
		}
		else {
			x = a2[ck.No].x;
			y = a2[ck.No].y;
			atk = a2[ck.No].atk;
			mv = a2[ck.No].mv;
		}
		temp = 1;
	}
	cout << sd << ' ' << x << ' ' << y << '\n';
	cin >> tox >> toy;
	movechess( x, y, tox, toy,mv);
}

int main() {	
	map_init();
	while (1) {
		while (waiting.front().time == 0) {
			checker ck = waiting.front();
			turn(ck);
			switch (ck.kind)
			{
			case 4:
			case 5:
				ck.time = 4;
				break;
			case 3:
				ck.time = 3;
			}
			waiting.erase(waiting.begin());
			wait_insert(ck);
		}
		timegoon();
	}
}